#ifndef __BLOCK_QUEUE__HPP__
#define __BLOCK_QUEUE__HPP__
#include <iostream>
#include <pthread.h>
#include <queue>
#include "Cond.hpp"
#include "Mutex.hpp"
#define DEF_CAP 5

namespace wxd
{
    template <class T>
    class BlockQueue
    {
    public:
        BlockQueue()
            : _csleep(0), _psleep(0), _capacity(DEF_CAP)
        {
        }
        ~BlockQueue()
        {
        }
        // 生产者入队
        void Enqueue(const T &data)
        {
            {
                LockGuard lock(&_mutex); // RAII

                while (_queue.size() >= _capacity) // 队列满，去等待 循环判断防止伪唤醒
                {
                    // 等待
                    _psleep++;
                    _full_cond.Wait(_mutex);
                    _psleep--;
                }
                // 入队
                _queue.push(data);
                std::cout << "生产了一个任务" << std::endl;

                // 唤醒消费者
                if (_csleep > 0)
                {
                    std::cout << "唤醒消费者" << std::endl;
                    _empty_cond.Signal();
                }
            }
        }
        // 消费者出队
        T Pop()
        {
            T data;
            {
                LockGuard lock(&_mutex);
                while (_queue.empty())
                {
                    // 等待
                    _csleep++;
                    _empty_cond.Wait(_mutex);
                    _csleep--;
                }

                // 出队
                data = _queue.front();
                _queue.pop();
                std::cout << "消费了一个任务" << std::endl;

                // 唤醒生产者
                if (_psleep > 0)
                {
                    std::cout << "唤醒生产者" << std::endl;
                    _full_cond.Signal();
                }
            }
            return data;
        }

    private:
        std::queue<T> _queue;
        Mutex _mutex;
        Cond _empty_cond;
        Cond _full_cond;
        size_t _csleep;
        size_t _psleep;
        size_t _capacity;
    };

}

#endif